package Servers

import (
	"GameLogic/AIRobot"
	"PBMessage"
	"SGNet"
	"container/list"
	proto "misc/protobuf/proto"
	log "misc/seelog"
	"strconv"
	cfg "utils/config"
	"utils/uuid"
)

type MatchGame struct {
	Hall         *HallServer
	MacthPlayers *list.List
	cacheplayers []*HallPlayer

	RobotWaitTime    int
	AddRobotWaitTime int
}

func NewMatchGame(hall *HallServer) *MatchGame {
	matchGame := &MatchGame{}
	matchGame.Hall = hall
	matchGame.cacheplayers = make([]*HallPlayer, matchGame.Hall.RoomSize)
	matchGame.MacthPlayers = list.New()
	matchGame.init()
	matchGame.RobotWaitTime, _ = strconv.Atoi(cfg.Get()["RobotWaitTime"])
	return matchGame
}

func (matchGame *MatchGame) init() {
	matchGame.Hall.AddNetHandler(PBMessage.PBID_CS_MatchGame, matchGame.CS_MatchGameHandler)
	matchGame.Hall.AddNetHandler(PBMessage.PBID_CS_CancelMatch, matchGame.CS_CancelMatchGameHandler)
}

func (matchGame *MatchGame) Add(hallPlayer *HallPlayer) {
	hallPlayer.MatchRef = matchGame.MacthPlayers.PushBack(hallPlayer)
}

func (matchGame *MatchGame) Remove(hallPlayer *HallPlayer) {
	matchGame.MacthPlayers.Remove(hallPlayer.MatchRef)
}

func (this *MatchGame) CanMatchTruePlayerGame() bool {
	truePlayerNumber := 0
	for e := this.MacthPlayers.Front(); e != nil; e = e.Next() {
		hallPlayer := e.Value.(*HallPlayer)
		if !hallPlayer.IsRobot() {
			truePlayerNumber++
		}
	}
	if truePlayerNumber >= this.Hall.RoomSize {
		return true
	}
	return false
}

func (matchGame *MatchGame) Loop() {
	if matchGame.CanMatchTruePlayerGame() {
		matchGame.MatchPlayersToReadyRoom()
		matchGame.AddRobotWaitTime = 0
		return
	}
	matchGame.AddRobotWaitTime++
	if matchGame.AddRobotWaitTime >= matchGame.RobotWaitTime && matchGame.MacthPlayers.Len() > 0 {

		matchGame.MatchPlayersToReadyRoom()
		matchGame.AddRobotWaitTime = 0
	}

}

func (matchGame *MatchGame) MatchPlayersToReadyRoom() {
	AIRobot.AIRobot.Load()
	truePlayerSize := 0
	cacheIndex := 0
	for e := matchGame.MacthPlayers.Front(); e != nil; e = e.Next() {
		player := e.Value.(*HallPlayer)
		matchGame.cacheplayers[cacheIndex] = player
		matchGame.MacthPlayers.Remove(player.MatchRef)
		player.MatchRef = nil
		truePlayerSize++
	}

	if truePlayerSize < matchGame.Hall.RoomSize {
		for i := truePlayerSize; i < matchGame.Hall.RoomSize; i++ {
			matchGame.cacheplayers[i] = NewHallPlayer(nil, nil, AIRobot.AIRobot.GenAIUnit())

		}
	}
	newReadyRoom := NewReadyRoom(matchGame.cacheplayers, uuid.NewV1().String(), matchGame.Hall)
	matchGame.Hall.AddReadyRoom(newReadyRoom)
	newReadyRoom.Update(0.01)
	newReadyRoom.Update(0.01)
	newReadyRoom.Update(0.01)
	newReadyRoom.EnterRoomToClient()
}

func (matchGame *MatchGame) CS_MatchGameHandler(msg *SGNet.Message) {
	matchGameData := &PBMessage.CS_MatchGame{}
	proto.Unmarshal(msg.Data, matchGameData)
	retMatchGame := &PBMessage.SC_RetMatchGame{RetType: proto.Int32(0)}

	if matchGame.Hall.GetPlayer(matchGameData.GetUserId()) == nil {
		retMatchGame.RetType = proto.Int32(0)
		msg.Sess.SendPacket(PBMessage.PBID_SC_RetMatchGame, retMatchGame)
		log.Info("错误的UserId")
		return
	}
	hallPlayer := matchGame.Hall.GetPlayer(matchGameData.GetUserId()).(*HallPlayer)
	log.Info("开始匹配" + hallPlayer.GetAccountModel().Account)
	hallPlayer.PlayerState = EnumPlayerState_MatchGame
	matchGame.Add(hallPlayer)
	msg.Sess.SendPacket(PBMessage.PBID_SC_RetMatchGame, retMatchGame)
}

func (matchGame *MatchGame) CS_CancelMatchGameHandler(msg *SGNet.Message) {
	cancelMatch := &PBMessage.CS_MatchGame{}
	proto.Unmarshal(msg.Data, cancelMatch)
	hallplayer := matchGame.Hall.GetPlayer(cancelMatch.GetUserId()).(*HallPlayer)
	matchGame.Remove(hallplayer)
	hallplayer.PlayerState = EnumPlayerState_Hall

	retCancelGame := &PBMessage.SC_RetCancelMatch{RetType: proto.Int32(0)}
	msg.Sess.SendPacket(PBMessage.PBID_SC_RetCancelMatch, retCancelGame)
}
